package com.drelephant.commons.util;

import com.drelephant.commons.Constants;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static java.beans.Introspector.getBeanInfo;

/**
 * @author wenshuai@hz-health.cn
 */
public class BeanUtil {

    public static boolean isBeanToMap(Object bean) {
        return bean != null && !ClassUtils.isPrimitiveOrWrapper(bean.getClass()) && bean.getClass() != BigDecimal.class
                && !bean.getClass().isEnum() && bean.getClass() != Date.class && bean.getClass() != String.class;
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> beanToMap(Object bean) {
        Map<String, Object> map = new HashMap<>();
        try {
            if (bean instanceof Map) {
                return (Map<String, Object>) bean;
            }
            // 获取所有的属性描述器
            final PropertyDescriptor[] pds = getBeanInfo(bean.getClass()).getPropertyDescriptors();
            for (PropertyDescriptor pd : pds) {
                if ("class".equals(pd.getName())) {
                    continue;
                }
                map.put(pd.getName(), pd.getReadMethod().invoke(bean));
            }
        } catch (Exception e) {
            throw new RuntimeException("转换错误", e);
        }
        return map;
    }

    /**
     * 将Map 转换成  key=value&key=value 字符串
     */
    public static String getSortKeyValueParam(Map<String, Object> map) {
        Collection<String> keySet = map.keySet();
        List<String> list = new ArrayList<>(keySet);
        Collections.sort(list);
        return list.stream()
                .filter(key->StringUtils.isNotBlank(key)&&null !=map.get(key))
                .map(data -> data + "=" + toString(map.get(data)))
                .collect(Collectors.joining("&"));
    }

    public static String toString(Object value) {
        return toString(value, StringUtils.EMPTY);
    }

    public static String toString(Object value, String defaultStr) {
        if (value instanceof Date) {
            return DateFormatUtils.format((Date) value, Constants.SHARE_DEFAULT_FORMAT);
        }
        return value != null ? value.toString() : defaultStr;
    }

    public static String toJsonString(Object data) throws JsonProcessingException {
        return JsonObjectMapperFactory.getInstance().writeValueAsString(data);
    }

    public static <T> T parseObject(String json, Class<T> clazz) throws IOException {
        return JsonObjectMapperFactory.getInstance().readValue(json, clazz);
    }

    public static class JsonObjectMapperFactory {
        private static final String DATE_FORMAT = Constants.SHARE_DEFAULT_FORMAT;
        private static ObjectMapper om = new ObjectMapper();

        static {
            om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            om.setDateFormat(new SimpleDateFormat(DATE_FORMAT));
            om.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            om.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        }

        public static ObjectMapper getInstance() {
            return om;
        }
    }
}
